<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div id="test">尚硅谷IT教育</div>

    <div id="demo">
      <ul>
        <li>test1</li>
        <li>test2</li>
        <li>test3</li>
        <li>test4</li>
        <li>test5</li>
      </ul>
    </div>

    <!--
    1. [].slice.call(伪数组): 将伪数组转换为真数组
    2. node.nodeType: 得到节点类型
    3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)// 注意: value,writable不能get和set同时出现
    4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
    5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
    6. DocumentFragment: 文档碎片(高效批量更新多个节点)
       6.1 创建fragment: document.createDocumentFragment()
       6.2 将dom节点添加到fragment中: fragment.appendChild(item)
       6.3 获取fragment的子节点: fragment.children
       6.4 把fragment里的子节点添加到页面中: document.querySelector('#demo').appendChild(fragment)
    7. RegExp.$1
    -->
    <script>
      // 1. 将伪数组转成真数组
      //#region
      // const lis = document.getElementsByTagName('li')
      // console.log(lis) //此时lis是伪数组

      //需求: 需要提供一个方法,比如叫clone.clone的作用就是克隆数组.谁调用这个clone,谁就被克隆,返回值就是克隆出来的新数组

      // Array.prototype.clone = function () {
      //   return this.map((item) => item)
      // }

      // const arr = [1, 2, 3]
      // const newArr = arr.clone()
      // console.log(newArr) // [1,2,3]
      // console.log(newArr === arr) // false

      // 数组的slice方法内部一定是通过this找到了被克隆的数组

      // const newArr = [].slice.call(lis) //返回值是一个数组
      // console.log(newArr)
      //#endregion

      // 2. node.nodeType 元素节点返回值为 1
      // console.log(document.getElementById('demo').nodeType)

      // 3. Object.defineProperty 用于重新定义指定对象中的指定属性
      //#region
      // let obj = { name: 'zs' }
      // let value = 123 // 这个value在get和set中使用
      // 往obj对象上添加xxx属性
      // Object.defineProperty(obj, 'xxx', {
      //   // value: 123, //初始化xxx的值
      //   // writable: true, // 是否可以被设置(赋值)
      //   enumerable: true, // 当前xxx是否可以被遍历
      //   configurable: false, // 当前xxx属性是否可以被删除
      //   // 注意: value和writable不能和get,set同时出现
      //   get() {
      //     console.log('get执行了', this)
      //     // 当访问obj.xxx时触发
      //     return value
      //   },
      //   set(newValue) {
      //     // 当修改obj.xxx时触发
      //     console.log('set执行了', newValue, this)
      //     value = newValue
      //     // this.xxx = newValue //注意: 千万不能直接在set中修改对象中xxx属性的值
      //   },
      // })
      // obj.xxx = 999
      // console.log(obj)

      // for (let key in obj) {
      //   console.log(key)
      // }
      // delete obj.xxx //删除obj对象的xxx属性
      // console.log(obj.xxx)
      // obj.xxx = 999
      // // console.log(obj.xxx)
      // console.log(obj)

      // 3.1 数据代理
      // 将一个对象(obj)上面的数据,代理到另一个对象(proxy)上.当获取proxy对象的数据时,其实获取的是obj的数据,修改proxy的数据是,其实修改的也是obj的数据
      // let name = 'zs'
      // let obj = {}
      // let proxy = {}

      // 实现:
      // Object.defineProperty(proxy, 'name', {
      //   get() {
      //     return obj.name
      //   },
      //   set(newValue) {
      //     obj.name = newValue
      //   },
      // })

      // 3.2 数据劫持(数据监视)
      // 数据劫持,其实就是监视数据什么时候被获取,什么时候被修改
      // 需求: 在obj.name被获取的时候,执行一个alert,提示一下obj.name被获取了. obj.name被修改的时候,执行一个alert,提示一下obj.name被修改了
      // Object.defineProperty(obj, 'name', {
      //   get() {
      //     console.log(`obj.name被获取了`)
      //     return name
      //   },
      //   set(newValue) {
      //     console.log(`obj.name被修改了`)
      //     name = newValue
      //   },
      // })

      //#endregion

      // 4. Object.keys(obj) 返回一个数组,数组中存储了obj的所有键
      // const obj = { name: 'zs', age: 18 }
      // console.log(Object.keys(obj))

      // 5. obj.hasOwnProperty(prop) 判断某个对象身上是否有某个属性
      // const obj = { name: 'zs' }
      // console.log(obj.hasOwnProperty('name')) //如果name是obj的属性,则返回true

      // Object.defineProperty(obj, 'age', {
      //   // value: 19,
      //   get() {
      //     return 19
      //   },
      // })
      // console.log(obj.hasOwnProperty('age'))

      // 6. 需求: 要替换当前页面中每一个li标签的内容
      // const lis = document.getElementsByTagName('li')
      // ;[].slice.call(lis).forEach((item) => {
      //   item.innerText = 'xxx'
      // })
      // 创建文档碎片
      // const fragment = document.createDocumentFragment()
      // // 将dom树上某个节点添加到文档碎片中(添加到文档碎片中的dom,会脱离dom树)
      // fragment.appendChild(document.querySelector('#demo ul'))

      // // 操作文档碎片中的节点
      // ;[].slice
      //   .call(fragment.children[0].children)
      //   .forEach((item) => (item.innerText = 'xxx'))

      // // 将文档碎片添加到dom树上,则文档碎片中的子节点会自动添加到dom树上
      // document.getElementById('demo').appendChild(fragment)

      // 7. RegExp.$1 提取正则中分组部分的信息

      const reg = /^(\d{4})-(\d{2})-(\d{2})$/ // '0000-00-00'

      let str = '2023-07-15'
      if (reg.test(str)) {
        console.log(RegExp.$1)
        console.log(RegExp.$2)
        console.log(RegExp.$3)
      }
    </script>
  </body>
</html>
